package com.lemon.tieba.user.web;

import com.lemon.common.constant.SessionContants;
import com.lemon.common.context.SessionContext;
import com.lemon.common.exception.ExceptionEnum;
import com.lemon.common.exception.BaseException;
import com.lemon.common.dto.Response;
import com.lemon.common.util.CookieUtils;
import com.lemon.tieba.user.domain.User;
import com.lemon.tieba.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 用户 Controller
 *
 * @author ymh
 * @date 2019-3-22 16:34
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 注册
     *
     * @param user
     * @return
     */
    @PostMapping("/regist")
    public ResponseEntity<User> regist(User user) {
        int count = userService.insert(user);
        if (count == 0) {
            throw new BaseException(ExceptionEnum.CREATE_FAILED);
        }
        return ResponseEntity.status(HttpStatus.OK).body(user);
    }

    /**
     * 登录
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/login")
    public ResponseEntity<User> login(String username, String password, HttpServletRequest req, HttpServletResponse resp) {
        User user = userService.login(username, password);
        if (user == null) {
            throw new BaseException(ExceptionEnum.LOGIN_FAILED);
        }

        // 登录用户信息保存在 session 中
        HttpSession session = req.getSession();
        session.setAttribute(SessionContants.SESSION_USER, user);
        // 创建 cookie 并将 sessionId 保存在其中发送回客户端
        Cookie cookie = new Cookie("JSESSIONID", session.getId());
        cookie.setMaxAge(60 * 24 * 7); // cookie 过期时间（分钟）
        cookie.setPath("/");
        resp.addCookie(cookie);

        // 日志
        log.info("用户 " + username + " 已登录");

        return ResponseEntity.status(HttpStatus.OK).body(user);
    }

    /**
     * 退出登录
     *
     * @param req
     * @param resp
     * @return
     */
    @GetMapping("/logout")
    public ResponseEntity<Response> logout(HttpServletRequest req, HttpServletResponse resp) {
        // 获取 Session
        Cookie cookie = CookieUtils.getCookie(req, "JSESSIONID");
        String sessionId = cookie.getValue();
        SessionContext sessionContext = SessionContext.getInstance();
        HttpSession session = sessionContext.getSession(sessionId);

        User user = (User) session.getAttribute(SessionContants.SESSION_USER);
        String username = user.getUsername();
        // 清除 Session 中所有数据
        session.invalidate();
        // 将 Session 从环境变量中删除
        sessionContext.delSession(session);
        // 销毁 Cookie
        CookieUtils.delCookie(req, resp, "JSESSIONID");

        // 日志
        log.info("用户 " + username + " 已退出登录");

        return ResponseEntity.status(HttpStatus.OK).body(new Response(200, "退出登录"));
    }

    /**
     * 从 session 中获取当前用户
     *
     * @param req
     * @return
     */
    @GetMapping("/current")
    public ResponseEntity<User> current(HttpServletRequest req) {
        // 获取 cookie
        Cookie cookie = CookieUtils.getCookie(req, "JSESSIONID");
        if (cookie == null) {
            throw new BaseException(ExceptionEnum.NOT_LOGIN);
        }

        // 通过 sessionId 获取 session
        String sessionId = cookie.getValue();
        SessionContext sessionContext = SessionContext.getInstance();
        HttpSession session = sessionContext.getSession(sessionId);
        if (session == null) {
            throw new BaseException(ExceptionEnum.NOT_LOGIN);
        }

        // 从 session 中获取用户信息
        User user = (User) session.getAttribute(SessionContants.SESSION_USER);
        if (user == null) {
            throw new BaseException(ExceptionEnum.NOT_LOGIN);
        }

        return ResponseEntity.status(HttpStatus.OK).body(user);
    }

    /**
     * 检查用户名是否重复
     *
     * @param username
     * @return
     */
    @GetMapping("/check/username")
    public ResponseEntity<User> checkUsername(String username) {
        User user = userService.selectByUsername(username);
        return ResponseEntity.status(HttpStatus.OK).body(user);
    }

    /**
     * 新增
     *
     * @param user
     * @return
     */
    @PostMapping
    public ResponseEntity<User> save(User user) {
        int count = userService.insert(user);
        if (count == 0) {
            throw new BaseException(ExceptionEnum.CREATE_FAILED);
        }
        return ResponseEntity.status(HttpStatus.OK).body(user);
    }

    /**
     * 修改
     *
     * @param user
     * @param req
     * @return
     */
    @PutMapping
    public ResponseEntity<Response> update(User user, HttpServletRequest req) {
        int count = userService.update(user);
        if (count == 0) {
            throw new BaseException(ExceptionEnum.UPDATE_FAILED);
        }

        // 更新 session 中的用户信息
        HttpSession session = req.getSession();
        session.setAttribute(SessionContants.SESSION_USER, user);
        return ResponseEntity.status(HttpStatus.OK).body(new Response(200, "修改成功"));
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @DeleteMapping("{id}")
    public ResponseEntity<Response> delete(@PathVariable Long id) {
        int count = userService.delete(id);
        if (count == 0) {
            throw new BaseException(ExceptionEnum.DELETE_FAILED);
        }
        return ResponseEntity.status(HttpStatus.OK).body(new Response(200, "删除成功"));
    }

}
